package com.sparkseries.route;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

/**
 * 网关动态路由服务
 *
 */
@Slf4j
@Service
public class DynamicRouteService implements ApplicationEventPublisherAware {
    @Resource
    private InMemoryRouteDefinitionRepository repository;
    private ApplicationEventPublisher publisher;

    private void informChanged() {
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    /**
     * 添加路由
     * TODO 为从Redis中读取路由使用
     * @param definition 路由定义
     * @return 添加状况
     */
    public String add(RouteDefinition definition) {
        log.info("Gateway Add Route : {}", definition);
        try {
            repository.save(Mono.just(definition)).subscribe();
            informChanged();
        } catch (Exception e) {
            log.error("添加路由异常", e);
        }
        return "Add Route Success";
    }

    /**
     * 更新路由
     *
     * @param definition 路由定义
     * @return 更新状况
     */
    public String update(RouteDefinition definition) {
        try {
            repository.delete(Mono.just(definition.getId()));
        } catch (Exception e) {
            log.error("Update Fail, Not Find Route -> RouteId: {}", definition.getId());
        }
        try {
            repository.save(Mono.just(definition)).subscribe();
            informChanged();
            return "Update Route Success";
        } catch (Exception e) {
            log.error("更新路由异常", e);
            return "Update Route Fail";
        }
    }

    /**
     * 删除路由
     * TODO 为从Redis中删除路由使用
     * @param routeId 路由名称
     * @return 删除状况
     */
    public String delete(String routeId) {
        log.info("Route Delete Route : {}", routeId);
        try {
            repository.delete(Mono.just(routeId)).subscribe();
            informChanged();
            return "Delete Route Success";
        } catch (Exception e) {
            log.error("删除路由异常", e);
            return "Delete Route Fail";
        }
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }
}
